﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Management;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace DSAL
{
    public static class SN
    {
        private static string Codes = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        private static string getcomputerbit(string softname)
        {
            string cpuID = GetCpuID();
            string bIOSSerialNumber = GetBIOSSerialNumber();
            string hardDiskSerialNumber = GetHardDiskSerialNumber();
            string netCardMACAddress = GetNetCardMACAddress();
            if (cpuID != "")
            {
                MD5 md = new MD5CryptoServiceProvider();
                cpuID = BitConverter.ToString(md.ComputeHash(Encoding.Default.GetBytes(cpuID))).Replace("-", "").ToUpper().Substring(8, 0x10);
                return (softname + "C" + cpuID);
            }
            if (bIOSSerialNumber != "")
            {
                MD5 md2 = new MD5CryptoServiceProvider();
                bIOSSerialNumber = BitConverter.ToString(md2.ComputeHash(Encoding.Default.GetBytes(bIOSSerialNumber))).Replace("-", "").ToUpper().Substring(8, 0x10);
                return (softname + "B" + bIOSSerialNumber);
            }
            if (hardDiskSerialNumber != "")
            {
                MD5 md3 = new MD5CryptoServiceProvider();
                hardDiskSerialNumber = BitConverter.ToString(md3.ComputeHash(Encoding.Default.GetBytes(hardDiskSerialNumber))).Replace("-", "").ToUpper().Substring(8, 0x10);
                return (softname + "H" + hardDiskSerialNumber);
            }
            if (netCardMACAddress != "")
            {
                MD5 md4 = new MD5CryptoServiceProvider();
                netCardMACAddress = BitConverter.ToString(md4.ComputeHash(Encoding.Default.GetBytes(netCardMACAddress))).Replace("-", "").ToUpper().Substring(8, 0x10);
                return (softname + "N" + netCardMACAddress);
            }
            return (softname + "WF53A419DB238BBAD");
        }

        #region utils
        private static string GetCpuID()
        {
            try
            {
                ManagementObjectCollection instances = new ManagementClass("Win32_Processor").GetInstances();
                string str = null;
                foreach (ManagementObject obj2 in instances)
                {
                    str = obj2.Properties["ProcessorId"].Value.ToString();
                    break;
                }
                return str;
            }
            catch
            {
                return "";
            }
        }

        private static string GetHardDiskSerialNumber()
        {
            try
            {
                ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");
                string str = "";
                foreach (ManagementObject obj2 in searcher.Get())
                {
                    str = obj2["SerialNumber"].ToString().Trim();
                    break;
                }
                return str;
            }
            catch
            {
                return "";
            }
        }

        private static string GetNetCardMACAddress()
        {
            try
            {
                ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapter WHERE ((MACAddress Is Not NULL) AND (Manufacturer <> 'Microsoft'))");
                string str = "";
                foreach (ManagementObject obj2 in searcher.Get())
                {
                    str = obj2["MACAddress"].ToString().Trim();
                }
                return str;
            }
            catch
            {
                return "";
            }
        }

        // Methods
        private static string GetBIOSSerialNumber()
        {
            try
            {
                ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * From Win32_BIOS");
                string str = "";
                foreach (ManagementObject obj2 in searcher.Get())
                {
                    str = obj2["SerialNumber"].ToString().Trim();
                }
                return str;
            }
            catch
            {
                return "";
            }
        }
        #endregion

        /// <summary>
        /// 获取计算机的序列号
        /// </summary>
        /// <param name="softName"></param>
        /// <param name="productType"></param>
        /// <returns></returns>
        public static string GetSerialNumber(string softName, string productType)
        {
            string computerbit = getcomputerbit(softName);

            bool flag = true;
            SHA1 sha2 = new SHA1CryptoServiceProvider();
            // len 40
            string str4 = BitConverter.ToString(sha2.ComputeHash(Encoding.Default.GetBytes(computerbit + productType))).Replace("-", "").ToUpper();
            string str5 = "";
            for (int i = 0; i < str4.Length; i++)
            {
                if ((i % 2) == 1)
                {
                    str5 = str5 + str4[i];
                }
            }
            string str6 = "";
            for (int j = 0; j < str4.Length; j++)
            {
                if ((j % 2) == 0)
                {
                    str6 = str6 + str4[j];
                }
            }
            int[] numArray = new int[20];
            for (int k = 0; k < 20; k++)
            {
                numArray[k] = str6[k] + str5[k];
                numArray[k] = numArray[k] % 0x24;
            }
            string str7 = "";
            for (int m = 0; m < 20; m++)
            {
                if ((m > 0) && ((m % 4) == 0))
                {
                    str7 = str7 + "-";
                }
                str7 = str7 + Codes[numArray[m]];
            }
            Console.WriteLine("序列号:" + str7);
            return str7;
        }
    }
}
